In a ripple counter, the input clock goes directly to only one flipflop, the LSB, and is cascaded to the others. This explains why the LSB always has to change state, and changes at a slightly different time to higher weight outputs.
In Gray code, any output may change state. It's therefore obvious that you can't have a ripple (asynchronous) implementation of a Gray counter that's as simple as a binary ripple counter.
A synchronous counter, on which all outputs change state on the same input edge, is not necessarily more reliable, it is just as reliable when its characteristics are taken into account when designing the system that uses it.
If a ripple and a synchronous counter are made from the same technology, the outputs of the synchronous counter will stop changing in a shorter time from the clock edge. However, the ripple counter will count correctly up to a higher input frequency. The ripple counter is guaranteed to have significant skew between the outputs, the synchronous counter might have some skew depending on how symmetrically it's been designed, and how equally loaded the outputs are. In both cases, read the data sheet, and design to accommodate the part's behaviour.
In a synchronous counter, the clock goes to all flipflops, and internal gating is used to decide which ones change state. Look at the internal diagram in the datasheet for an HC163 to see this for instance. Seen like this, the HC163 is just a 16 state state machine, with the sequence through the output states controlled by the internal gating. To alter the output sequence, to Gray code for instance, is only a matter of altering the state decoding.
Obviously you need a suitable target to implement such a decode and control circuit. You could do it from discretes, HC74s and HC86s for instance. Or with VHDL on a CPLD or FPGA target. Be warned that for the discrete case, if you go for a minimum gate solution, which will mean cascading down the XORs, it will be a little slower than the binary version.
An alternative way to get a Gray weighted count is to use a binary counter, and recode the outputs. This may seem like cheating a bit, but with the decoding already done for you to make an HC163 work, it's probably the easiest way to do it in discretes. It's probably also the fastest, as the HC163 outputs are registered. Encode the binary outputs to Gray with an XOR cascade, then register them again on the same clock. I fear this last one isn't in the spirit of what you're trying to do.
Perhaps a route closer to a 'ripple counter' or asynchronous Gray counter is suggested by the observation that the 'LSB' changes state every other clock input. If the LSB is a T type (a 'toggle' latch, also constructable as a JK with J and K tied together, or an XOR wrapped round a D latch), then a single asynchronous divide by 2 can control that to flip state every other input. A higher bit changes state when the LSB doesn't, and according to other conditions. See if you can figure out the gating for a 2 bit, and then how it changes to a 3 bit Gray counter, then you'll have the pattern for constructing the cascade for the n bit Gray counter.