I don't know much about python/numpy internals, but here's what I assume is happening. By just looking at the code, I get the impression that finline is doing more work than freturn, since finline has all the statements that freturn does (x + 1.0) and more.
Maybe this explains what's going on:
>>> x = np.random.rand(N)
>>> y = np.zeros(N)
>>> super(np.ndarray, y).__repr__()
Out[33]: '<numpy.ndarray object at 0x24c9c80>'
>>> finline(x, y)
>>> y # see that y was modified
Out[35]:
array([ 1.92772158, 1.47729293, 1.96549695, ..., 1.37821499,
1.8672971 , 1.17013856])
>>> super(np.ndarray, y).__repr__()
Out[36]: '<numpy.ndarray object at 0x24c9c80>' # address of y did not change
>>> y = freturn(x)
>>> super(np.ndarray, y).__repr__()
Out[38]: '<numpy.ndarray object at 0x24c9fc0>' # address of y changed
So essentially, I think that finline is doing more work because it has to iterate over the elements of y and initialize each of them to the array returned by the x + 1.0 operation. On the other hand, y = freturn(x) probably just reinitializes the value of the y pointer to be equal to the address of the array initialized by the x + 1.0 operation.