In the Optional lab  Feature Engineering and Polynomial Regression
We created a new feature, x^2 as follows:
create target data
x = np.arange(0, 20, 1)
y = 1 + x**2
Engineer features
X = x**2 #< added engineered feature
And then the Gradient descent function was called with X:
model_w,model_b = run_gradient_descent_feng(X, y, iterations=10000, alpha = 1e5)
I can understand this, as now instead of x, we have x^2
However, we go on to add more engineered features, like x^3:
create target data
x = np.arange(0, 20, 1)
y = x**2
engineer features
X = np.c_[x, x2, x3] #< added engineered feature
and call the gradient descent with X:
model_w,model_b = run_gradient_descent_feng(X, y, iterations=10000, alpha=1e7)
I have two questions:

Why is the model function given as y = x2 ?
Should it not be y = x + x2 + x**3 + b 
Donâ€™t understand how X can be an array with 3 columns, and this goes as an argument in the function call to calculate the y estimate, and y itself is defined with only x**2
Any help appreciated.