Let me break that down into several questions:
What is a variable?
A variable is a storage location that contains a value.
Why are value types called value types?
The value of a variable of value type is a value, and is copied by value. The value of a variable of reference type is a reference and is copied by reference. That is why value types are called value types and reference types are called reference types.
Why does a.Height = 10 work?
To change the value stored in a variable of reference type, you've got to have a variable to begin with. In this case, you do: you have the variable "a". The compiler compiles that as "pass the managed address of the variable 'a' to the Height setter with the argument 10". Therefore the Height property setter knows how to find the location of the value stored in 'a' and mutate it.
Why does a.Size.Height = 10 not work?
To change the value stored in a variable of reference type, you've got to have a variable to begin with. The expression "a.Size" is not a variable; it is a value. a.Size does not give you the variable that backs the property -- in fact, there might not be one. Instead, it gives you the value of the property. Value types are copied by value; this is a copy of the value of the property. This means that the compiler has two choices: it can copy the value into a temporary variable and then mutate that variable, tricking you into thinking that you've mutated the backing store of a.Size. Or, it can give you an error indicating that you're doing something foolish. It does the latter.
Isn't this confusing and vexing?
Yes. The moral of the story is do not make mutable value types. Only make immutable value types. Never have a setter on a value type in the first place; only do the assignment in the constructor. If the thing has to be mutable, make it a reference type.
Do I have to use "new" to make a new instance of a value type?
No. You can also use "default":
Foo f = default(Foo);
If Foo is a value type then this fills in the contents of storage location f with the Foo which has all its fields set to their default values.
Or, if the value type is mutable, you can simply set the values of all the fields. However, you have to set all of them if you do not use a constructor or the default initializer. You have to set all of them including private fields.
But if a struct has all public fields doesn't that violate best practices guidelines in two ways? First, because it has public fields, and second, because it is a mutable value type?
Yes. Don't do that.