1 of 2

Python, 107 bytes

from random import*
lambda s:''.join([choice(c+c.swapcase()),'_'][c<'!']for c in sorted(s,key=str.isdigit))

An improvement on the other two Python answers because:

  • [...,'_'][c<'!'] is used instead of s.replace(' ','_'), and
  • choice(c+c.swapcase()) is used instead of choice([c.upper(),c.lower()])