It is. From my understanding, CPUs execute machine code. Assembly has to be passed through an assembler to get machine code, and that assembler can make other changes as well, so they are not always one to one. Written assembly will usually translate veryclosely to machine code, though.
In short, assembly for a given CPU is very nearly one-to-one with the machine language for that CPU. It's not correct to conflate the two, but close enough when speaking informally.
While it's true that assembler doesn't quite fit into the same class as compiled/interpreted languages, it would be disingenuous to say it's not a programming language. It's simply a very low-level, machine specific one.
It's even blurrier when you consider that most modern assembler dialects have plenty of high level functionality (structs, macros, labels, etc) that do not correlate to machine instructions.