Why separate .h and .m files?
Historically, in C, when you included a .h file, it was almost literally equivalent to pasting the file into the file that included it. Effectively, all your declarations were repeated in every file that used them. That's ok, in C you can repeat declarations all you want, as long as they don't change. However, repeating definitions would result in multiple copies of a function and general brokenness. Therefore you couldn't include the whole code of a module, only its declarations.
I think Objective-C is actually smarter, and you could if you want have no .m files at all, and put all the code in .h files. You could also define a class only in a .m file and have no .h file, but you couldn't really make a whole project like that, since nothing would be able to access anything else.
However, it's still good practice to separate declarations from definitions. It's like having a menu at a restaurant instead of having to go back into the kitchen and see what's cooking. The .h file is a short summary of how other modules can make use of a module's contents.
Why some instance variables have properties and some do not?
Correct, part of it is that instance variables aren't automatically available to other classes. Properties by default are. However, not necessarily. You can make a property private.
Another thing you get with properties is automatic memory management. If you use the retain attribute, when you assign a value to a property, the value's retain count is increased, and the previous value's retain count (if any) is decreased. It's very convenient and avoids goof-ups. Even if other classes don't access the instance variable, it's useful. If you don't use properties, you have to make sure you do the appropriate retain and release instructions within your instance methods to avoid leaking memory. There are other automatic behaviors you can get on properties too, like locking or copying.
Lastly, you can get built-in behaviors with property attributes and the @synthesize keyword, but you can also decide not to use the @synthesize keyword, and write custom getters and setters for your properties. Those can do fancy things, like update related instance variables whenever a property is changed.