Your use of vectorized has problems because it has to guess as to the returned array dtype. Your function returns a list, not a number. So we need to specify the return dtype - as object:
In [25]: x = [0, 1, 2, 0, 0, 2, 1, 1]
...: colours = [[0, 0, 0], [255, 0, 0], [0, 255, 0], [0, 0, 255]]
...:
...: coloured = lambda v: colours[int(v)]
...: vcoloured = np.vectorize(coloured, otypes=[object])
In [26]: vcoloured(x)
Out[26]:
array([list([0, 0, 0]), list([255, 0, 0]), list([0, 255, 0]),
list([0, 0, 0]), list([0, 0, 0]), list([0, 255, 0]),
list([255, 0, 0]), list([255, 0, 0])], dtype=object)
That could be turned into a 2d array with:
In [27]: np.stack(_)
Out[27]:
array([[ 0, 0, 0],
[255, 0, 0],
[ 0, 255, 0],
[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 255, 0],
[255, 0, 0],
[255, 0, 0]])
But vectorize is not a performance tool (read its docs). It's faster to use a list comprehension:
In [28]: np.array([colours[v] for v in x])
Out[28]:
array([[ 0, 0, 0],
[255, 0, 0],
[ 0, 255, 0],
[ 0, 0, 0],
[ 0, 0, 0],
[ 0, 255, 0],
[255, 0, 0],
[255, 0, 0]])
The direct array indexing of @Mad's answer is better.