Ruby doesn't encourage you think in multiple layers of abstraction. The
next step down from C is a simple machine model with instructions, a CPU,
and memory, which is actually kind of helpful for writing code and
understanding performance.

Vaguely. The "C is close to hardware" point has been well put to rest by folks with better knowledge on the compiler intricacies than I. C gives you the illusion of knowing what you are doing. Your mental model does not help you much in C, at least not in modern C on modern architectures. The next step down from C is object code generated for a specific OS in a specific memory model with a spiderweb of links to other libraries. After that, the OS processes that object code, sending instructions to your hardware, a complicated machine model that includes instruction pipelining, memory pages, and so forth, all of which are difficult to handle by hand without a clear understanding of the interactions. You pointed that out, but you oversimplified the issue.

Fortunately, we are rescued from having to have that much understanding by the C language, which abstracts a lot of concepts nicely. I should point out that printf(), the first output anyone learns in C, has its own language for outputing in the form of format specifiers, far removed from direct machine code. Which instruction do you use for "i = i * 2"? a multiplier or a shift? Some developers rewrite malloc() because of various inefficiencies in the way it manages memory, but the beginner can understand malloc() on a very simple level and be successful.

The nice thing about ruby, python, perl, java, and many other languages is that you do not have to worry about the memory drudgery. In all likelihood, you are going to do it wrong anyway. If I am teaching beginners algorithms, well, we can focus on memory management techniques later. We can still understand that there is a computer with a CPU and some memory available to us.

My point is that you do not have to understand all these layers of abstraction. It is nice to know something of them later, and we are all better developers for it. In fact, knowing a little about garbage collection of your specific language can, for example, help you avoid circular reference memory leaks.

When syntax has no pretension to correspond to natural language syntax, it
encourages a more appropriate mindset.

This is what I mean about being shackled by our languages. We come to believe there is some "appropriate mindset". In fact, the language of choice creates the mindset, and your approach to an algorithm will depend on your ability to translate your will into that language's primitives, means of combination, and means of abstraction. Functional languages are the latest fad in part because programmers in general have rediscovered that method of thinking; as you put it, they have had a "dominant, inappropriate mental model [that holds] back their learning". Our beginners were shown the "i = i + 1" pattern and not shown the "for my $i (1 .. 8) {}" pattern.

Sure, natural languages may never be natural enough; two individuals in the same room do not necessarily speak the same English. You have to draw the line somewhere. It just does not have to be at rock bottom, and we have continued to evolve, making layer after layer on top of it. We are corresponding here on a medium that is many levels abstracted from the silicon, and many a beginner in web design can grasp plenty of HTML without understanding how a specific browser is rendering it.

I would argue more optimistically that this is not a matter of somebody's learning being held back. They learned and applied a method that is valid. When that method became insufficient, bug-ridden, poorly optimized, whatever, they learned or experimented with a new approach. This is not holding anyone back in any meaningful sense; they are evolving.