Создать объектный массив dtype легко:
In [550]: arr = np.empty(5, object)
In [551]: arr
Out[551]: array([None, None, None, None, None], dtype=object)
Вы можете заполнить его из списка объектов:
In [552]: arr[:] = [np.arange(i) for i in range(5)]
In [553]: arr
Out[553]:
array([array([], dtype=int64), array([0]), array([0, 1]),
array([0, 1, 2]), array([0, 1, 2, 3])], dtype=object)
фактически вы можете создать массив прямо из списка:
In [554]: np.array([np.arange(i) for i in range(5)])
Out[554]:
array([array([], dtype=int64), array([0]), array([0, 1]),
array([0, 1, 2]), array([0, 1, 2, 3])], dtype=object)
In [555]: np.array([np.arange(3) for i in range(5)])
Out[555]:
array([[0, 1, 2],
[0, 1, 2],
[0, 1, 2],
[0, 1, 2],
[0, 1, 2]])
Назначение предопределенного массива более надежно:
In [561]: arr[:]=[np.arange(3) for i in range(5)]
In [562]: arr
Out[562]:
array([array([0, 1, 2]), array([0, 1, 2]), array([0, 1, 2]),
array([0, 1, 2]), array([0, 1, 2])], dtype=object)
Иногда в таком назначении могут возникать ошибки трансляции.
Но в любом случае вам все равно нужно создать объекты, которые вы собираетесь назначить массиву, и при этом трудно избежать циклов - по крайней мере, не в самых общих случаях.