Here's a simple scanline algorithm you can use:
Work through your grid row by row: left to right, top to bottom.
As you come to each cell, the two cells adjacent above it and the one cell adjacent to its left in the same row have already had tiles assigned. The rest aren't assigned yet, so we won't worry about them.
Our three already-assigned neighbours have used at most three of the available tiles (sometimes two, if they alternate A-B-A or at the start of a narrow row, or one for cells at the top & leftmost edges, or zero for the top-left cell)
Mark those tiles forbidden, and count how many tiles you marked. Subtract that from 9 to get the number of options for this cell.
Generate a random number
i between 0 and this number of options. Take the
ith non-forbidden tile from your list and assign it to this cell.
Clear the forbidden marking from the tiles used by the left & top-left neighbours and proceed to the next cell.
Since we only ever forbid at most 3 tiles at a time, we always have at least 6 options for the next tile. And because we never place a tile that matches an adjacent tile that's already placed, we're guaranteed to produce a valid colouring with no identical tiles side-by-side.
We only have to read 3 neighbours at each step, and in fact you can exploit the pattern of travel to slim this down even further - the top-right neighbour of this cell is also the top-left neighbour of the next cell, and the cell we just assigned is the left neighbour of the next cell, so we don't need to check them again. Apart from a little set-up at the start of a row, we only actually have to check one new neighbour for each cell we want to assign. How's that for magic? :)