From the append documentation:
Definition: append(arr, values, axis=None)
Docstring:
Append values to the end of an array.
Parameters
----------
arr : array_like
Values are appended to a copy of this array.
values : array_like
These values are appended to a copy of `arr`. It must be of the
correct shape (the same shape as `arr`, excluding `axis`). If `axis`
is not specified, `values` can be any shape and will be flattened
before use.
axis : int, optional
The axis along which `values` are appended. If `axis` is not given,
both `arr` and `values` are flattened before use.
That is, why your example (1) fails is that as you don't specify an axis argument for the first append, x is flattened, and hence the second append fails as the shapes no longer match.
Your second example fails because the shapes don't match. At the start, x.shape = (1,0), that is 1 row and 0 columns. Then you try to add an array with shape (1,2) along the 0'th axis (that is, you want the result array to have more rows but the same number of columns) which of course doesn't work since the number of columns doesn't match.
As an aside, personally I almost never use append() when working with numpy. It's much more efficient to allocate the correct size upfront and then use slicing to fill it in rather than using append which implies a reallocation and copy every time.