A non-numpy solution is
In [10]: zip(a,b)
Out[10]: [([1], [6]), ([2], [7]), ([3], [8]), ([4], [9]), ([5], [10])]
Oops - not quite. Without the inner brackets, zip does a nice job of regrouping lists:
In [11]: zip([1,2,3],[4,5,6])
Out[11]: [(1, 4), (2, 5), (3, 6)]
Playing around a bit more, I get
In [12]: zip(zip(*a)[0],zip(*b)[0])
Out[12]: [(1, 6), (2, 7), (3, 8), (4, 9), (5, 10)]
I'm also a big fan of list comprehensions. They are a form of looping, but compact and about as fast as possible with plain Python. Here too I need [0] to pull terms out of the inner lists.
In [25]: [[i[0],j[0]] for i,j in zip(a,b)]
Out[25]: [[1, 6], [2, 7], [3, 8], [4, 9], [5, 10]]
itertools.chain is another good tool for flattening nested lists:
In [31]: zip(*(itertools.chain(*a),itertools.chain(*b)))
Out[31]: [(1, 6), (2, 7), (3, 8), (4, 9), (5, 10)]
But since you mention numpy we can use:
In [18]: np.concatenate((a,b),axis=1)
Out[18]:
array([[ 1, 6],
[ 2, 7],
[ 3, 8],
[ 4, 9],
[ 5, 10]])
The basic concatenate works because np.array(a) produces a (5,1) array. So 2 such arrays can be joined into a (5,2) array without any further shape adjustment.
To get back to the nested list format, use tolist on that array.
In [19]: np.concatenate((a,b),axis=1).tolist()
Out[19]: [[1, 6], [2, 7], [3, 8], [4, 9], [5, 10]]
hstack and column_stack also join on the 1 axis, adjusting dimensions if needed. But I like the explicit control that np.concatenate gives (and requires).