OK, even more investigation and I think the method needed to create a train route involving tunnels is actually the "problem"!
Taking my example setup above - Station A <---->Tunnel B<---->Tunnel C<---->Station D
To create a route to get a train to shuttle backwards and forwards between Station A and Station D then I need to do the following;
1. Create a double-ended train and place it between A and B
2. Create a route for the train starting at A and going to B (at this point the only two available stations will be A & B with C & D greyed out as inaccessible)
3. Manually move the train so that it is underground between B and C
4. Add C to the train's route (at this point the only two available stations will be B & C with A & D greyed out as inaccessible)
5. Manually move the train back above ground so it's between C and D
6. Add D to the train's route (at this point the only two available stations will be C & D with A & B greyed out as inaccessible)
7. Then add C to the route to begin the train's return journey
8. Manually move the train so that it is back underground between B and C
9. Add B to the train's route (at this point the only two available stations will be B & C with A & D greyed out as inaccessible)
10. Take the train back above ground to be between A and B
11. Set the train to automatic and it should begin shuttling from A to D and then back to A
Apologies if this was obvious to everyone else but it wasn't obvious to me and I couldn't find it detailed step-by-step anywhere else!
I am guessing (can anyone confirm?) that the way Factorio works is that each station maintains a static routing table entry for every other station connected to it. However, stations cannot "see" stations that are only connected to it via an underground track section, Hence, station A can see B but not C or D. However, the train dynamically updates its route as it reaches each station named on its route. So, when the train starts off from A, it knows how to get to the next station on its route (B) and doesn't mind that it doesn't know how to get to C or D. Then, when it arrives at station B, the train learns from B how to get to C because B can see both A and C. In turn, when the train arrives at C it learns how to get to D. The train then makes its way back to A using the same method.
So, I'm not sure if I have it 100% right but it now works for me.