If you're open to a sliiiightly different approach, may I heartily recommend use-package? Rather than "attempt to use, check for error, install if error," use-package will, on first install, check if the package exists at all and install it if needed. It's also effectively a deferred require, which can be very nice for managing package existence without bogging down loading.
This does, of course, mean you have to be sure use-package is installed properly, but the up-side is you only have to manually ensure a single package. I do this as @Tobias suggested, with an addition:
;; Be sure we've fetched the package archive at least once before
;; attempting to install anything.
(unless package-archive-contents
(package-refresh-contents))
;; Manually check for `use-package`, install if needed
(unless (package-installed-p 'use-package)
(package-install 'use-package))
Do note: in the case of auctex specifically, the use-package declaration takes a particular form:
(use-package tex
:ensure auctex)
This is due to an idiosyncracy of auctex itself; see this question and very thorough answer for details.