I think enumerating the cases along the way makes it a bit more tangible for the discussion
import numpy as np
z = 1+1j
z.conjugate() # 1-1j
zz = np.array(z)
zz # array(1+1j)
zz.T # array(1+1j) # OK expected.
zz.conj() # 1-1j ?? what happened; no arrays?
zz.conjugate() # 1-1j ?? same
zz1d = np.array([z]*3)
zz1d.T # no change so this is not the regular 2D array
zz1d.conj() # array([1.-1.j, 1.-1.j, 1.-1.j])
zz1d.conj().T # array([1.-1.j, 1.-1.j, 1.-1.j])
zz1d.T.conj() # array([1.-1.j, 1.-1.j, 1.-1.j])
zz1d[:, None].conj() # 2D column vector - no surprises if [:, None] is known
zz2d = zz1d[:, None] # 2D column vector - no surprises if [:, None] is known
zz2d.conj() # 2D col vec conjugated
zz2d.conj().T # 2D col vec conjugated transposed
zz3d = np.arange(24.).reshape(2,3,4).view(complex)
zz3d.conj() # no surprises, conjugated
zz3d.conj().T # ?? Why not the last two dims swapped like other stacked ops
# For scalar arrays conjugation strips the number
# For 1D arrays transpose is a no-op but conjugation works
# For 2D arrays conjugate it is the matlab's elementwise conjugation op .'
# and transpose is acting like expected
# For 3D arrays conjugate it is the matlab's elementwise conjugation op .'
# but transpose is the reversing all dims just like matlab's permute()
# with static dimorder.
and so on. Maybe we can try to identify all the use cases and the quirks before we can make design the solution. Because these are a bit more involved and I don't even know if this is exhaustive.