I'll present an example for smaller value of n:
n = 4
First create a full array with results of your function:
arr = np.fromfunction(f, (n,n), dtype='complex')
So far the result (with reduced precision) is:
array([[ 0.     +0.j, -0.5    +0.5j    , -0.8    +0.4j    , -0.9    +0.3j    ],
       [ 0.5    +0.j,  0.2    +0.6j    , -0.25   +0.75j   , -0.53846+0.69231j],
       [ 0.66667+0.j,  0.5    +0.5j    ,  0.15385+0.76923j, -0.16667+0.83333j],
       [ 0.75   +0.j,  0.64706+0.41176j,  0.4    +0.7j    ,  0.12   +0.84j   ]])
Then, to generate your expected result, run:
result = [ [i,j, arr[i,j]] for i, j in zip(*np.triu_indices(n)) ]
The result is a list of lists containing:
[[0, 0, 0j]],
 [0, 1, (-0.5    +0.5j)]],
 [0, 2, (-0.8    +0.4j)],
 [0, 3, (-0.89999+0.3j)],
 [1, 1, ( 0.2    +0.6j)],
 [1, 2, (-0.25   +0.75j)],
 [1, 3, (-0.53846+0.69231j)],
 [2, 2, ( 0.15385+0.76923j)],
 [2, 3, (-0.16667+0.83333j)],
 [3, 3, ( 0.12   +0.84j)]]
(I also reduced the precision).
If you run into problems concerning available memory, then don't create
any temporary array, but run instead:
result = [ [i, j, f(i,j)] for i, j in zip(*np.triu_indices(n)) ]
But this variant will run significantly slower than using np.fromfunction.