Your example, and an expanded version for time tests:
In [202]: a=np.array([[5,4],[6,7,2],[8,1,9]],dtype=object)
In [203]: A = a.repeat(100)
Applying Python list sort to each element:
In [204]: np.array([sorted(i) for i in a])
Out[204]: array([list([4, 5]), list([2, 6, 7]), list([1, 8, 9])], dtype=object)
Using frompyfunc to do the same:
In [205]: np.frompyfunc(sorted,1,1)(a)
Out[205]: array([list([4, 5]), list([2, 6, 7]), list([1, 8, 9])], dtype=object)
Some timings:
In [206]: timeit np.array(list(map(sorted, A)))
168 µs ± 221 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [207]: timeit np.array([sorted(i) for i in A])
181 µs ± 249 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
map is a little faster than a list comprehension. I prefer the readability of the comprehension.
A pure list version is quite a bit faster:
In [208]: %%timeit temp=A.tolist()
...: list(map(sorted, temp))
...:
...:
88.3 µs ± 70.8 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
frompyfunc is faster than the array map, and almost as good as the pure list version:
In [209]: timeit np.frompyfunc(sorted,1,1)(A)
97.3 µs ± 1.93 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
That's the pattern I've seen before. frompyfunc is the fastest way to apply functions to elements of an object dtype array, but it seldom is better than a list based iteration.
frompyfuncoften is twice as fast as iteration when working with the elements of a object array.